package com.example.execption;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 定义全局异常处理器
 * 实现功能：希望程序抛出异常的时候有人处理，并且返回一个标准响应格式给用户
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private final Logger log=LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class) //声明处理所有异常
    @ResponseBody  //Object--json
    public Object handlerException(Exception e)
    {
        //1.对于异常要重视，要日志输出
        log.error("exception:"+e);
        //2.返回一个标准响应格式给用户
        return ApiRestResponse.error(TijianExceptionEnum.SYSTEM_ERROR);
    }

    @ExceptionHandler(TijianException.class) //声明只处理商城业务异常
    @ResponseBody  //Object--json
    public Object NeueduMallException(TijianException e)
    {
        //1.对于异常要重视，要日志输出
        log.error("exception:"+e);
        //2.返回一个标准响应格式给用户
        return ApiRestResponse.error(e.getCode(),e.getMessage());
    }

    @ExceptionHandler(BindException.class) //声明只处理参数校验异常
    @ResponseBody  //Object--json
    public Object BindException(BindException e)
    {
        //1.对于异常要重视，要日志输出
        log.error("exception:"+e);
        //2.返回一个标准响应格式给用户
        return handleBindingResult(e.getBindingResult());
    }

    //处理参数校验未通过是的报错信息，把它们封装到响应的结果中
    private Object handleBindingResult(BindingResult bindingResult)
    {
        List<Object> list=new ArrayList<>();//准备装校验的出错信息
        if(bindingResult.hasErrors()) {
            List<ObjectError> errors=bindingResult.getAllErrors();

            for(ObjectError error:errors)
            {
                list.add(error.getDefaultMessage());
            }
        }
        if(list.size()==0) {
            //如果出错了，但是没有出错信息，那么只给前台状态码和描述信息
            return ApiRestResponse.error(TijianExceptionEnum.REQUEST_PARAM_ERROR);
        }else
        {
            //如果出错了，并且有出错信息，那么给前台状态码和描述信息还有出错信息
            return ApiRestResponse.error(TijianExceptionEnum.REQUEST_PARAM_ERROR.getCode(),
                    TijianExceptionEnum.REQUEST_PARAM_ERROR.getMessage(),list.toString());
        }
    }
}